package com.sqlcheck.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.sqlcheck.dto.response.DashboardStatisticsVO;
import com.sqlcheck.entity.CompatibilityRule;
import com.sqlcheck.entity.ScanResult;
import com.sqlcheck.entity.ScanTask;
import com.sqlcheck.entity.SqlStatement;
import com.sqlcheck.enums.TaskStatus;
import com.sqlcheck.repository.CompatibilityRuleRepository;
import com.sqlcheck.repository.ScanResultRepository;
import com.sqlcheck.repository.ScanTaskRepository;
import com.sqlcheck.repository.SqlStatementRepository;
import com.sqlcheck.service.DashboardService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class DashboardServiceImpl implements DashboardService {

    private final ScanTaskRepository scanTaskRepository;
    private final SqlStatementRepository sqlStatementRepository;
    private final ScanResultRepository scanResultRepository;
    private final CompatibilityRuleRepository compatibilityRuleRepository;

    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Override
    public DashboardStatisticsVO getDashboardStatistics(Long userId) {
        log.info("获取仪表盘统计信息, userId: {}", userId);

        return DashboardStatisticsVO.builder()
                .taskStatistics(getTaskStatistics(userId))
                .sqlStatementStatistics(getSqlStatementStatistics(userId))
                .issueStatistics(getIssueStatistics(userId))
                .ruleStatistics(getRuleStatistics())
                .recentTasks(getRecentTasks(5, userId))
                .systemStatus(getSystemStatus())
                .build();
    }

    @Override
    public DashboardStatisticsVO.TaskStatistics getTaskStatistics(Long userId) {
        QueryWrapper<ScanTask> wrapper = new QueryWrapper<>();
        if (userId != null) {
            wrapper.eq("user_id", userId);
        }
        wrapper.eq("deleted", false);

        List<ScanTask> tasks = scanTaskRepository.selectList(wrapper);

        long totalTasks = tasks.size();
        long completedTasks = tasks.stream().filter(t -> TaskStatus.SUCCESS.equals(t.getStatus())).count();
        long runningTasks = tasks.stream()
                .filter(t -> TaskStatus.RUNNING.equals(t.getStatus()) || TaskStatus.PENDING.equals(t.getStatus()))
                .count();
        long failedTasks = tasks.stream().filter(t -> TaskStatus.FAILED.equals(t.getStatus())).count();
        long pendingTasks = tasks.stream().filter(t -> TaskStatus.PENDING.equals(t.getStatus())).count();

        return DashboardStatisticsVO.TaskStatistics.builder()
                .totalTasks(totalTasks)
                .completedTasks(completedTasks)
                .runningTasks(runningTasks)
                .failedTasks(failedTasks)
                .pendingTasks(pendingTasks)
                .build();
    }

    @Override
    public DashboardStatisticsVO.SqlStatementStatistics getSqlStatementStatistics(Long userId) {
        QueryWrapper<SqlStatement> wrapper = new QueryWrapper<>();
        if (userId != null) {
            // 通过task_id关联到用户
            QueryWrapper<ScanTask> taskWrapper = new QueryWrapper<>();
            taskWrapper.eq("user_id", userId).eq("deleted", false);
            List<ScanTask> userTasks = scanTaskRepository.selectList(taskWrapper);
            List<Long> taskIds = userTasks.stream().map(ScanTask::getId).collect(Collectors.toList());

            if (taskIds.isEmpty()) {
                return DashboardStatisticsVO.SqlStatementStatistics.builder()
                        .totalStatements(0L)
                        .statementsByType(new HashMap<>())
                        .statementsBySource(new HashMap<>())
                        .ddlStatements(0L)
                        .queryStatements(0L)
                        .dmlStatements(0L)
                        .build();
            }

            wrapper.in("task_id", taskIds);
        }
        wrapper.eq("deleted", false);

        List<SqlStatement> statements = sqlStatementRepository.selectList(wrapper);

        long totalStatements = statements.size();
        long ddlStatements = statements.stream().filter(s -> s.getSqlType() == SqlStatement.SqlType.DDL).count();
        long queryStatements = statements.stream().filter(s -> s.getSqlType() == SqlStatement.SqlType.QUERY).count();
        long dmlStatements = statements.stream().filter(s -> s.getSqlType() == SqlStatement.SqlType.DML).count();

        Map<String, Long> statementsByType = statements.stream()
                .collect(Collectors.groupingBy(s -> s.getSqlType().name(), Collectors.counting()));

        Map<String, Long> statementsBySource = statements.stream()
                .collect(Collectors.groupingBy(s -> s.getSourceType().name(), Collectors.counting()));

        return DashboardStatisticsVO.SqlStatementStatistics.builder()
                .totalStatements(totalStatements)
                .statementsByType(statementsByType)
                .statementsBySource(statementsBySource)
                .ddlStatements(ddlStatements)
                .queryStatements(queryStatements)
                .dmlStatements(dmlStatements)
                .build();
    }

    @Override
    public DashboardStatisticsVO.IssueStatistics getIssueStatistics(Long userId) {
        QueryWrapper<ScanResult> wrapper = new QueryWrapper<>();
        if (userId != null) {
            // 通过task_id关联到用户
            QueryWrapper<ScanTask> taskWrapper = new QueryWrapper<>();
            taskWrapper.eq("user_id", userId).eq("deleted", false);
            List<ScanTask> userTasks = scanTaskRepository.selectList(taskWrapper);
            List<Long> taskIds = userTasks.stream().map(ScanTask::getId).collect(Collectors.toList());

            if (taskIds.isEmpty()) {
                return DashboardStatisticsVO.IssueStatistics.builder()
                        .totalIssues(0L)
                        .highSeverityIssues(0L)
                        .mediumSeverityIssues(0L)
                        .lowSeverityIssues(0L)
                        .infoIssues(0L)
                        .issuesByCategory(new HashMap<>())
                        .build();
            }

            wrapper.in("task_id", taskIds);
        }
        wrapper.eq("deleted", false);

        List<ScanResult> issues = scanResultRepository.selectList(wrapper);

        long totalIssues = issues.size();
        long highSeverityIssues = issues.stream()
                .filter(i -> "HIGH".equals(i.getSeverity() != null ? i.getSeverity().name() : null)).count();
        long mediumSeverityIssues = issues.stream()
                .filter(i -> "MEDIUM".equals(i.getSeverity() != null ? i.getSeverity().name() : null)).count();
        long lowSeverityIssues = issues.stream()
                .filter(i -> "LOW".equals(i.getSeverity() != null ? i.getSeverity().name() : null)).count();
        long infoIssues = issues.stream()
                .filter(i -> "INFO".equals(i.getSeverity() != null ? i.getSeverity().name() : null)).count();

        Map<String, Long> issuesByCategory = issues.stream()
                .filter(i -> i.getIssueType() != null)
                .collect(Collectors.groupingBy(i -> i.getIssueType().name(), Collectors.counting()));

        return DashboardStatisticsVO.IssueStatistics.builder()
                .totalIssues(totalIssues)
                .highSeverityIssues(highSeverityIssues)
                .mediumSeverityIssues(mediumSeverityIssues)
                .lowSeverityIssues(lowSeverityIssues)
                .infoIssues(infoIssues)
                .issuesByCategory(issuesByCategory)
                .build();
    }

    @Override
    public DashboardStatisticsVO.RuleStatistics getRuleStatistics() {
        List<CompatibilityRule> rules = compatibilityRuleRepository.selectList(null);

        long totalRules = rules.size();
        long activeRules = rules.stream().filter(CompatibilityRule::getIsActive).count();
        long inactiveRules = totalRules - activeRules;

        Map<String, Long> rulesByCategory = rules.stream()
                .collect(Collectors.groupingBy(CompatibilityRule::getCategory, Collectors.counting()));

        Map<String, Long> rulesBySeverity = rules.stream()
                .collect(Collectors.groupingBy(r -> r.getSeverity().name(), Collectors.counting()));

        return DashboardStatisticsVO.RuleStatistics.builder()
                .totalRules(totalRules)
                .activeRules(activeRules)
                .inactiveRules(inactiveRules)
                .rulesByCategory(rulesByCategory)
                .rulesBySeverity(rulesBySeverity)
                .build();
    }

    @Override
    public List<DashboardStatisticsVO.RecentTaskVO> getRecentTasks(Integer limit, Long userId) {
        QueryWrapper<ScanTask> wrapper = new QueryWrapper<>();
        if (userId != null) {
            wrapper.eq("user_id", userId);
        }
        wrapper.eq("deleted", false)
                .orderByDesc("updated_at")
                .last("LIMIT " + (limit != null ? limit : 5));

        List<ScanTask> tasks = scanTaskRepository.selectList(wrapper);

        return tasks.stream().map(task -> {
            // 获取任务的SQL语句数量
            Long sqlStatementCount = (long) sqlStatementRepository.countByTaskId(task.getId());

            // 获取任务的问题数量
            QueryWrapper<ScanResult> issueWrapper = new QueryWrapper<>();
            issueWrapper.eq("task_id", task.getId()).eq("deleted", false);
            Long issueCount = (long) scanResultRepository.selectCount(issueWrapper);

            return DashboardStatisticsVO.RecentTaskVO.builder()
                    .id(task.getId())
                    .taskName(task.getTaskName())
                    .taskType(task.getTaskType() != null ? task.getTaskType().name() : null)
                    .status(task.getStatus() != null ? task.getStatus().name() : null)
                    .progress(task.getProgress())
                    .createdAt(task.getCreatedAt() != null ? task.getCreatedAt().format(DATE_FORMATTER) : null)
                    .updatedAt(task.getUpdatedAt() != null ? task.getUpdatedAt().format(DATE_FORMATTER) : null)
                    .sqlStatementCount(sqlStatementCount)
                    .issueCount(issueCount)
                    .build();
        }).collect(Collectors.toList());
    }

    @Override
    public DashboardStatisticsVO.SystemStatus getSystemStatus() {
        return DashboardStatisticsVO.SystemStatus.builder()
                .serviceStatus("RUNNING")
                .serviceVersion("1.0.0")
                .databaseStatus("CONNECTED")
                .lastUpdateTime(LocalDateTime.now().format(DATE_FORMATTER))
                .healthCheckStatus(true)
                .build();
    }
}